#include <stdio.h>
#include <stdlib.h>

struct list_element {
 struct list_element *prev;
 struct list_element *next;
 int value; };

struct list {
 struct list_element *first;
 struct list_element *last; };
 
 
struct list_element *list_new_elem (int value)
 {
  struct list_element *elem;

  elem = malloc (sizeof (struct list_element));
  if (!elem) { return (NULL); }

  elem->prev = elem;
  elem->next = elem;
  elem->value = value;

  return (elem);
 }

struct list *list_new (void)
 {
  struct list *list = malloc (sizeof (struct list));;

  if (!list) { return (NULL); }
  list->first = NULL;
  list->last  = NULL;

  return (list);
 }

void list_append (struct list *list, int value)
 {
  struct list_element *elem = NULL;
  //TODO moet hier geen malloc? 
  // (miss niet omdit dit pointer is en geen daadwerkelijke content)

  if (!list) { return; }

  elem = list_new_elem(value);
  if (!elem) { return; }

  if (list->first == NULL && list->last == NULL)
   {
    list->first = elem;
    list->last  = elem;
    elem->prev  = elem;
    elem->next  = elem;
   }
   else
   {
    elem->prev = list->last;
    elem->next = list->first;
    // TODO deze dubbele linking zal apart geschreven moeten worden 
    // (beschreven als bug op Toledo)
    struct list_element *tmp = NULL;
    tmp = list->last;
    tmp->next = elem;
    //list->last->next = elem;
    tmp = list->first;
    tmp->prev = elem;
    //list->first->prev = elem;
    list->last = elem;
   }

  return;
 }

void list_remove (struct list *list, struct list_element *elem)
 {
  if (!elem || !list) { return; }

  if (elem == list->first && elem == list->last)
   {
    list->first = NULL;
    list->last  = NULL;
   }
   else if (elem == list->first)
   {
    list->first = elem->next;
    list->first->prev = list->last;
   }
   else if (elem == list->last)
   {
    list->last = elem->prev;
    list->last->next = list->first;
   }
   else
   {
    elem->prev->next = elem->next;
    elem->next->prev = elem->prev;
   }

  //free (elem->value);
  free (elem);

  return;
 }

void list_release (struct list *list)
 {
  struct list_element *elem;

  if (!list) { return; }

  elem = list->first;
  while (elem)
   {
    list_remove (list, elem);
    elem = list->first;
   }

  free (list);

  return;
 }
 
 
void printList (struct list *list)
 {
  struct list_element *elem = NULL;
  unsigned int i;

  elem = list->first;
  i = 0;
  while (elem)
   {
     printf ("%d\n", elem->value);

     if (elem == list->last)
      { elem = NULL; }
      else
      { elem = elem->next; }
     i++; }

  return;
 }
 
void main() {
  struct list *list = NULL;
  list = list_new ();
  list_append(list, 1);
  list_append(list, 2);
  list_append(list, 3);
  
  //list_release(list);
  
  
  printList(list);
 }
